package com.ruoyi.system.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.Compute;
import com.ruoyi.system.domain.ComputeDetail;
import com.ruoyi.system.domain.DoseDetail;
import com.ruoyi.system.domain.dto.DoseDetail_compute;
import com.ruoyi.system.mapper.ComputeDetailMapper;
import com.ruoyi.system.mapper.ComputeMapper;
import com.ruoyi.system.mapper.DoseDetailMapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.QuantifyMapper;
import com.ruoyi.system.domain.Quantify;
import com.ruoyi.system.service.IQuantifyService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 计算外Service业务层处理
 *
 * @author ruoyi
 * @date 2024-09-01
 */
@Service
public class QuantifyServiceImpl implements IQuantifyService {
    @Resource
    private QuantifyMapper quantifyMapper;
    @Resource
    private DoseDetailMapper doseDetailMapper;
    @Resource
    private ComputeMapper computeMapper;
    @Resource
    private ComputeDetailMapper computeDetailMapper;

    /**
     * 查询计算外
     *
     * @param id 计算外主键
     * @return 计算外
     */
    @Override
    public Quantify selectQuantifyById(Long id) {
        return quantifyMapper.selectQuantifyById(id);
    }

    /**
     * 查询计算外列表
     *
     * @param quantify 计算外
     * @return 计算外
     */
    @Override
    public List<Quantify> selectQuantifyList(Quantify quantify) {
        return quantifyMapper.selectQuantifyList(quantify);
    }

    /**
     * 新增计算外
     *
     * @param quantify 计算外
     * @return 结果
     */
    @Override
    public int insertQuantify(Quantify quantify) {
        quantify.setCreateTime(DateUtils.getNowDate());
        return quantifyMapper.insertQuantify(quantify);
    }

    /**
     * 修改计算外
     *
     * @param quantify 计算外
     * @return 结果
     */
    @Override
    public int updateQuantify(Quantify quantify) {
        quantify.setUpdateTime(DateUtils.getNowDate());
        return quantifyMapper.updateQuantify(quantify);
    }

    /**
     * 批量删除计算外
     *
     * @param ids 需要删除的计算外主键
     * @return 结果
     */
    @Override
    public int deleteQuantifyByIds(Long[] ids) {
        return quantifyMapper.deleteQuantifyByIds(ids);
    }

    /**
     * 删除计算外信息
     *
     * @param id 计算外主键
     * @return 结果
     */
    @Override
    public int deleteQuantifyById(Long id) {
        return quantifyMapper.deleteQuantifyById(id);
    }

    /**
     * 算量
     */
    @Override
    @Transactional
    public void compute(String weekStart, String weekEnd) {
        Quantify quantify = new Quantify();
        quantify.setName(weekStart + " 至 " + weekEnd + "算量");
        quantify.setCreateTime(DateUtils.getNowDate());
        quantifyMapper.insertQuantify(quantify);

        final String weekStart_final = weekStart;
        final String weekEnd_final = weekEnd;

        Map<String, Object> params = new HashMap<String, Object>();
        params.put("weekStart", weekStart_final);
        params.put("weekEnd", weekEnd_final);
        List<DoseDetail_compute> doseDetailComputes = doseDetailMapper.computeDoseDetail(params);
        Integer batchNum = Integer.valueOf(RandomStringUtils.random(6, false, true));
        doseDetailComputes.forEach(item -> {
            item.setQuantifyId(quantify.getId());
            item.setBatchNum(batchNum);
            item.setWeekStart(weekStart_final);
            item.setWeekEnd(weekEnd_final);
        });
        computeMapper.insertComputeBatch(new HashMap<String, Object>() {{
            put("computes", doseDetailComputes);
        }});

        List<Compute> computes = computeMapper.selectComputeList(new Compute() {{
            setBatchNum(batchNum);
        }});

        ExecutorService executorService = Executors.newFixedThreadPool(6);

        List<ComputeDetail> detailList = new ArrayList<>(10);
        List<Future<List<ComputeDetail>>> taskList = new ArrayList<Future<List<ComputeDetail>>>();
        List<Callable<List<ComputeDetail>>> tasks = new ArrayList<>(10);
        computes.forEach(item -> {
            tasks.add(new AsyncTask(item, doseDetailMapper));
        });
        try {
            List<Future<List<ComputeDetail>>> futures = executorService.invokeAll(tasks);

            for (Future<List<ComputeDetail>> future : futures) {
                detailList.addAll(future.get());
            }
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        computeDetailMapper.insertComputeDetailBatch(new HashMap<String, Object>() {{
            put("details", detailList);
        }});


    }

    private static class AsyncTask implements Callable<List<ComputeDetail>> {

        private final Compute compute;
        private final DoseDetailMapper doseDetailMapper;

        public AsyncTask(Compute compute, DoseDetailMapper doseDetailMapper) {
            this.compute = compute;
            this.doseDetailMapper = doseDetailMapper;
        }

        @Override
        public List<ComputeDetail> call() throws Exception {
            List<ComputeDetail> computeDetailList = new ArrayList<>(10);
            DoseDetail doseDetail = new DoseDetail();
            doseDetail.setTypeId(compute.getTypeId());
            doseDetail.getParams().put("weekStart", compute.getWeekStart());
            doseDetail.getParams().put("weekEnd", compute.getWeekEnd());
            doseDetail.setTypeId(compute.getTypeId());
            doseDetail.setSpecId(compute.getSpecId());
            doseDetail.setBrandId(compute.getBrandId());
            List<DoseDetail> doseDetails = doseDetailMapper.selectDoseDetailList(doseDetail);
            doseDetails.forEach(item -> {
                ComputeDetail computeDetail = new ComputeDetail();
                computeDetail.setComputeId(compute.getId());
                computeDetail.setDoseId(item.getOrderId());
                computeDetail.setSchoolId(item.getSchoolId());
                computeDetail.setTypeId(item.getTypeId());
                computeDetail.setSpecId(item.getSpecId());
                computeDetail.setBrandId(item.getBrandId());
                computeDetail.setNum(item.getNum());
                computeDetail.setWeek(item.getWeek());
                computeDetailList.add(computeDetail);
            });
            return computeDetailList;
        }
    }

}
